package com.gpj.sqlbuilder.template;

import com.gpj.sqlbuilder.sysfun.SystemFunction;
import com.gpj.sqlbuilder.utils.ReflectUtil;
import com.gpj.sqlbuilder.utils.TextUtils;
import org.apache.commons.lang3.StringUtils;

/**
 * @className BaseTemplate
 * @description
 *   基本模板类,用于定义一些公共方法
 * @author GPJ
 * @date 2021/4/16 20:47
 * @version 1.0
 **/
public abstract class BaseTemplate extends Template{
	public BaseTemplate(int start, int tail, Template parent) {
		super(start, tail, parent);
	}

	abstract protected void doBuild();

	protected void build(){
		sql = new StringBuffer();
		doBuild();
	}

	/**
	 * 处理文本中的函数和变量,生成真正的SQL语句
	 * @param text 待处理函数和变量的文本
	 */
	protected StringBuffer text2Sql(StringBuffer text){
		StringBuffer data = new StringBuffer(text);
		data = AnalysisFunction(data);
		return AnalysisVariable(data);
	}

	/**
	 * 解析模板中的变量
	 */
	protected StringBuffer AnalysisVariable(StringBuffer sql){
		return TextUtils.findAndReplace("${*}", sql,
				(start, end, value) -> String.valueOf(queryVariableByName(value)));
	}

	/**
	 * 解析模板中的函数
	 * @param template 模板
	 */
	protected StringBuffer AnalysisFunction(StringBuffer template){
		return TextUtils.findAndReplace("#[*]", template, (start, end, value) -> {
			String[] info = value.split("\\|");
			String functionName = info[0];
			String[] params = info[1].split(",");

			Object[] args = new Object[params.length];
			for (int i = 0; i < params.length; i++) {
				args[i] = param2Obj(params[i].trim());
			}
			return String.valueOf(ReflectUtil.invoke(SystemFunction.class, functionName, args));
		});
	}

	/**
	 * 将参数转化为对象
	 * @param param 参数
	 */
	private Object param2Obj(String param){
		if(TextUtils.isRound("${*}", param)){
			return queryVariableByName(TextUtils.roundValue("${*}", param));
		}else if(TextUtils.isRound("'*'", param)){
			return TextUtils.roundValue("'*'", param);
		}else if(StringUtils.equals("true", param) || StringUtils.equals("true", param)){
			return Boolean.valueOf(param);
		}else if(param.indexOf("\\.") != -1){
			return Double.valueOf(param);
		}
		return param;
	}

	/**
	 * 变量名称获取变量值
	 * @param variableName
	 * @return
	 */
	protected Object queryVariableByName(String variableName){
		String[] names = variableName.split("\\.");

		Object variable = getVariableByName(names[0]);

		if(variable == null) return null;

		for (int i = 1; i < names.length; i++) {
			variable = ReflectUtil.getValueByMethod(variable, names[i]);
		}
		return variable;
	}

	/**
	 * 从子节点开始向根节点遍历模板树,查找当前变量名所对应的变量值
	 * @param variableName 要找的变量名
	 */
	private Object getVariableByName(String variableName){
		Template element = this;
		while (true){
			if(element.getVariables().containsKey(variableName)){
				return element.getVariables().get(variableName);
			}else if((element = element.getParent()) == null){
				return null;
			}
		}
	}
}
